package cz.muni.fi.pa165.travelagency.persistence;

import cz.muni.fi.pa165.travelagency.entities.Tour;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

/**
 * Data access object for tours
 *
 * @author Petr Stribny
 * @created 08-11-2012
 * @version 1.0
 */
@Repository
@Component
public class TourDAO implements ITourDAO {

    @PersistenceContext
    private EntityManager em;

    void setEntityManager(EntityManager em) {
        this.em = em;
    }

    @Override
    public void createTour(Tour tour) {
        if (tour == null) {
            throw new IllegalArgumentException("Tour cannot be null.");
        }

        if (tour.getId() != null) {
            throw new IllegalStateException("Id has to be null.");
        }

        if (tour.getName() == null || tour.getName().isEmpty()) {
            throw new IllegalArgumentException("Name has to be set.");
        }

        if (tour.getCapacity() <= 0) {
            throw new IllegalArgumentException("Capacity has to be greater than zero.");
        }

        if (tour.getPricePerPerson().intValue() <= 0) {
            throw new IllegalArgumentException("Price has to be greater than zero.");
        }

        if (tour.getDate() == null) {
            throw new IllegalArgumentException("Date has to be set.");
        }

        if (!tour.getDate().after(new Date())) {
            throw new IllegalArgumentException("Date has to be in the future!");
        }

        persist(tour);        
    }

    @Override
    public void deleteTour(Tour tour) {
        if (tour == null) {
            throw new IllegalArgumentException("Tour cannot be null.");
        }

        if (tour.getId() == null) {
            throw new IllegalStateException("Id cannot be null.");
        }
   
        delete(tour.getId());
    }

    @Override
    public Tour getTour(Long id) {
        if (id == null) {
            throw new IllegalArgumentException("Id cannot be null.");
        }

        Tour tour = null;
        try {
            tour = em.find(Tour.class, id);
        } catch (Throwable t) {
            throw new DAOException(t.getMessage(), t);
        }    

        return tour;
    }

    @Override
    public void updateTour(Tour tour) {
        if (tour == null) {
            throw new IllegalArgumentException("Tour cannot be null.");
        }

        if (tour.getId() == null) {
            throw new IllegalStateException("Id cannot be null.");
        }

        if (tour.getName() == null || tour.getName().isEmpty()) {
            throw new IllegalArgumentException("Name has to be set.");
        }

        if (tour.getCapacity() <= 0) {
            throw new IllegalArgumentException("Capacity has to be greater than zero.");
        }

        if (tour.getPricePerPerson().intValue() <= 0) {
            throw new IllegalArgumentException("Price has to be greater than zero.");
        }

        if (tour.getDate() == null) {
            throw new IllegalArgumentException("Date has to be set.");
        }

        if (!tour.getDate().after(new Date())) {
            throw new IllegalArgumentException("Date has to be in the future!");
        }

        try {
            em.merge(tour);
        } catch (Throwable t) {
            throw new DAOException(t.getMessage(), t);
        }
    }
    
    private synchronized void persist(Object object) {
        try {
            em.persist(object);
        } catch (Throwable t) {
            throw new DAOException(t.getMessage(), t);
        }

    }

    private synchronized void delete(Long id) {
        try {
            Tour pt = em.find(Tour.class, id);
            if (pt != null) {
                em.remove(pt);
            }
        } catch (Throwable t) {
            throw new DAOException(t.getMessage(), t);
        }

    }
}
